home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 April / enter-2004-04.iso / files / httrack-3.30.exe / {app} / src / htsserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-10-04  |  56.1 KB  |  1,815 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: Mini-server                                            */
  34. /* Author: Xavier Roche                                         */
  35. /* ------------------------------------------------------------ */
  36.  
  37.  
  38. /* specific definitions */
  39. /* specific definitions */
  40. #include "htsbase.h"
  41. #include "htsnet.h"
  42. #include "htslib.h"
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <time.h>
  47. #include <fcntl.h>
  48. #if HTS_WIN
  49. #else
  50. #include <arpa/inet.h>
  51. #endif
  52. #ifndef _WIN32
  53. #include <signal.h>
  54. #endif
  55. /* END specific definitions */
  56.  
  57. /* dΘfinitions globales */
  58. #include "htsglobal.h"
  59.  
  60. /* htslib */
  61. /*#include "htslib.h"*/
  62.  
  63. /* HTTrack Website Copier Library */
  64. #include "httrack-library.h"
  65.  
  66. /* Language files */
  67. #include "htsinthash.h"
  68. int NewLangStrSz=1024;
  69. inthash NewLangStr=NULL;
  70. int NewLangStrKeysSz=1024;
  71. inthash NewLangStrKeys=NULL;
  72. int NewLangListSz=1024;
  73. inthash NewLangList=NULL;
  74. /* Language files */
  75.  
  76.  
  77. #include "htsserver.h"
  78.  
  79. char* gethomedir(void);
  80. int commandRunning = 0;
  81. int commandEndRequested = 0;
  82. int commandEnd = 0;
  83. int commandReturn = 0;
  84. char* commandReturnMsg = NULL;
  85. char* commandReturnCmdl = NULL;
  86. int commandReturnSet = 0;
  87.  
  88. /* Extern */
  89. extern void webhttrack_main(char* cmd);
  90. extern void webhttrack_lock(int lock);
  91.  
  92. static int is_image(char* file) {
  93.   return ( (strstr(file, ".gif") != NULL) );
  94. }
  95. static int is_text(char* file) {
  96.   return ( (strstr(file, ".txt") != NULL) );
  97. }
  98. static int is_html(char* file) {
  99.   return ( (strstr(file, ".htm") != NULL) );
  100. }
  101.  
  102. static void sig_brpipe( int code ) {
  103.   /* ignore */
  104. }
  105.  
  106.  
  107. // URL Link catcher
  108.  
  109. // 0- Init the URL catcher with standard port
  110.  
  111. // smallserver_init(&port,&return_host);
  112. T_SOC smallserver_init_std(int* port_prox,char* adr_prox) {
  113.   T_SOC soc;
  114.   int try_to_listen_to[]={8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
  115.                           32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,
  116.                           42000,42001,42002,42003,42004,42005,42006,42007,42008,42009,
  117.                           0,-1};
  118.   int i=0;
  119.   do {
  120.     soc=smallserver_init(&try_to_listen_to[i],adr_prox);
  121.     *port_prox=try_to_listen_to[i];
  122.     i++;
  123.   } while( (soc == INVALID_SOCKET) && (try_to_listen_to[i]>=0));
  124.   return soc;
  125. }
  126.  
  127.  
  128. // 1- Init the URL catcher
  129.  
  130. // smallserver_init(&port,&return_host);
  131. T_SOC smallserver_init(int* port,char* adr) {
  132.   T_SOC soc = INVALID_SOCKET;
  133.   char h_loc[256+2];
  134.   
  135.   commandRunning = 
  136.     commandEnd = 
  137.     commandReturn = 
  138.     commandReturnSet =
  139.     commandEndRequested = 0;
  140.   if (commandReturnMsg)
  141.     free(commandReturnMsg);
  142.   commandReturnMsg = NULL;
  143.   if (commandReturnCmdl)
  144.     free(commandReturnCmdl);
  145.   commandReturnCmdl = NULL;
  146.  
  147.   if (gethostname(h_loc,256)==0) {    // host name
  148.     SOCaddr server;
  149.     int server_size=sizeof(server);
  150.     /*t_hostent* hp_loc;
  151.     t_fullhostent buffer;*/
  152.  
  153.     // effacer structure
  154.     memset(&server, 0, sizeof(server));
  155.     
  156.     /*if ( (hp_loc=vxgethostbyname(h_loc, &buffer)) )*/ {  // notre host      
  157.  
  158.       // copie adresse
  159.       // NO (bind all)
  160.       // SOCaddr_copyaddr(server, server_size, hp_loc->h_addr_list[0], hp_loc->h_length);
  161.  
  162.       SOCaddr_initany(server, server_size); 
  163.       if ( (soc=socket(SOCaddr_sinfamily(server), SOCK_STREAM, 0)) != INVALID_SOCKET) {
  164.         SOCaddr_initport(server, *port);
  165.         if ( bind(soc,(struct sockaddr*) &server, server_size) == 0 ) {
  166.           /*int len;
  167.           SOCaddr server2;
  168.           len=sizeof(server2);*/
  169.           // effacer structure
  170.           /*memset(&server2, 0, sizeof(server2));
  171.           if (getsockname(soc,(struct sockaddr*) &server2,&len) == 0) {
  172.             *port=ntohs(SOCaddr_sinport(server));  // rΘcupΘrer port*/
  173.             if (listen(soc,10)>=0) {    // au pif le 10
  174.               // SOCaddr_inetntoa(adr, 128, server2, len);
  175.               strcpy(adr, h_loc);
  176.             } else {
  177. #ifdef _WIN32
  178.               closesocket(soc);
  179. #else
  180.               close(soc);
  181. #endif
  182.               soc=INVALID_SOCKET;
  183.             }
  184.             
  185.             
  186.           /*} else {
  187. #ifdef _WIN32
  188.             closesocket(soc);
  189. #else
  190.             close(soc);
  191. #endif
  192.             soc=INVALID_SOCKET;
  193.           }*/
  194.           
  195.           
  196.         } else {
  197. #ifdef _WIN32
  198.           closesocket(soc);
  199. #else
  200.           close(soc);
  201. #endif
  202.           soc=INVALID_SOCKET;
  203.         }
  204.       }
  205.     }
  206.   }
  207.   return soc;
  208. }
  209.  
  210. // 2 - Wait for URL
  211.  
  212. static int recv_bl(T_SOC soc, void* buffer, size_t len, int timeout) {
  213.   if (check_readinput_t(soc, timeout)) {
  214.     int n = 1;
  215.     size_t size = len;
  216.     size_t offs = 0;
  217.     while(n > 0 && size > 0) {
  218.       n = recv(soc, ((char*)buffer) + offs, (int) size, 0);
  219.       if (n > 0) {
  220.         offs += n;
  221.         size -= n;
  222.       }
  223.     }
  224.     return (int)offs;
  225.   }
  226.   return -1;
  227. }
  228.  
  229.  
  230. // smallserver
  231. // returns 0 if error
  232. // url: buffer where URL must be stored - or ip:port in case of failure
  233. // data: 32Kb
  234.  
  235. typedef struct {
  236.   char* name;
  237.   int value;
  238. } initIntElt;
  239. typedef struct {
  240.   char* name;
  241.   char* value;
  242. } initStrElt;
  243.  
  244. int smallserver_setkey(char* key, char* value) {
  245.   return inthash_write(NewLangList, key, (unsigned long int)strdup(value));
  246. }
  247. int smallserver_setkeyint(char* key, LLint value) {
  248.   char tmp[256];
  249.   sprintf(tmp, LLintP, value);
  250.   return inthash_write(NewLangList, key, (unsigned long int)strdup(tmp));
  251. }
  252. int smallserver_setkeyarr(char* key, int id, char* key2, char* value) {
  253.   char tmp[256];
  254.   sprintf(tmp, "%s%d%s", key, id, key2);
  255.   return inthash_write(NewLangList, tmp, (unsigned long int)strdup(value));
  256. }
  257.  
  258. #define SET_ERROR(err) do { \
  259.   inthash_write(NewLangList, "error", (unsigned long int)strdup(err)); \
  260.   error_redirect = "/server/error.html"; \
  261. } while(0)
  262.  
  263. int smallserver(T_SOC soc,char* url,char* method,char* data, char* path) {
  264.   int timeout=30;
  265.   int retour=0;
  266.   int willexit=0;
  267.   int buffer_size = 32768;
  268.   char* buffer = (char*)malloc(buffer_size);
  269.   String headers = STRING_EMPTY;
  270.   String output = STRING_EMPTY;
  271.   String tmpbuff = STRING_EMPTY;
  272.   String fspath = STRING_EMPTY;
  273.  
  274.   /* Load strings */
  275.   htslang_init();
  276.   if (!htslang_load(NULL, path)) {
  277.     fprintf(stderr, "unable to find lang.def and/or lang/ strings in %s\n", path);
  278.     return 0;
  279.   }
  280.   LANG_T(path, 0);
  281.  
  282.   /* Init various values */
  283.   {
  284.     char pth[1024];
  285.     char* initOn[] = { "parseall", "Cache", "ka", 
  286.       "cookies", "parsejava", "testall", "updhack", "index", NULL };
  287.     initIntElt initInt[] = {
  288.       { "filter", 4 },
  289.       { "travel", 2 },
  290.       { "travel2", 1 },
  291.       { "travel3", 1 },
  292.       /* */
  293.       { "connexion", 4 },
  294.       /* */
  295.       { "maxrate", 25000 },
  296.       /* */
  297.       { "build", 1 },
  298.       /* */
  299.       { "checktype", 2},
  300.       { "robots", 3 },
  301.  
  302.       { NULL, 0 } 
  303.     };
  304.     initStrElt initStr[] = {
  305.       { "user", "Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)" },
  306.       { "footer", "<!-- Mirrored from %s%s by HTTrack Website Copier/3.x [XR&CO'2002], %s -->" },
  307.       { "url2", "+*.png +*.gif +*.jpg +*.css +*.js -ad.doubleclick.net/*" },
  308.       { NULL, NULL }
  309.     };
  310.     int i = 0;
  311.     for(i = 0 ; initInt[i].name ; i++) {
  312.       char tmp[32];
  313.       sprintf(tmp, "%d", initInt[i].value);
  314.       inthash_write(NewLangList, initInt[i].name, (unsigned long int)strdup(tmp));
  315.     }
  316.     for(i = 0 ; initOn[i] ; i++) {
  317.       inthash_write(NewLangList, initOn[i], (unsigned long int)strdup("1"));  /* "on" */
  318.     }
  319.     for(i = 0 ; initStr[i].name ; i++) {
  320.       inthash_write(NewLangList, initStr[i].name, (unsigned long int)strdup(initStr[i].value));
  321.     }
  322.     strcpybuff(pth, gethomedir());
  323.     strcatbuff(pth, "/websites");
  324.     inthash_write(NewLangList, "path", (unsigned long int)strdup(pth));
  325.   }
  326.  
  327.   /* Lock */
  328.   webhttrack_lock(1);
  329.  
  330.   // connexion (accept)
  331.   while(!willexit && buffer != NULL && soc != INVALID_SOCKET) {
  332.     char line1[1024];
  333.     char line[8192];
  334.     char line2[1024];
  335.     T_SOC soc_c;
  336.     struct sockaddr dummyaddr;
  337.     int dummylen = sizeof(struct sockaddr);
  338.     LLint length = 0;
  339.     char* error_redirect = NULL;
  340.  
  341.     line[0] = '\0';
  342.     buffer[0] = '\0';
  343.     StringClear(&headers);
  344.     StringClear(&output);
  345.     StringClear(&tmpbuff);
  346.     StringClear(&fspath);
  347.     StringStrcat(&headers, "");
  348.     StringStrcat(&output, "");
  349.     StringStrcat(&tmpbuff, "");
  350.     StringStrcat(&fspath, "");
  351.     memset(&dummyaddr, 0, sizeof(dummyaddr));
  352.  
  353.     /* UnLock */
  354.     webhttrack_lock(0);
  355.  
  356.     /* sigpipe */
  357. #ifndef _WIN32
  358.     signal( SIGPIPE , sig_brpipe );
  359. #endif
  360.  
  361.     /* Accept */
  362.     while ( (soc_c = accept(soc, &dummyaddr, &dummylen)) == INVALID_SOCKET);
  363.  
  364.     /* Lock */
  365.     webhttrack_lock(1);
  366.  
  367.     if(linputsoc_t(soc_c, line1, sizeof(line1) - 2, timeout) > 0) {
  368.       int meth = 0;
  369.       if (strfield(line1, "get ")) {
  370.         meth = 1;
  371.       } else if (strfield(line1, "post ")) {
  372.         meth = 2;
  373.       } else if (strfield(line1, "head ")) {   /* yes, we can do that */
  374.         meth = 10;
  375.       } else {
  376. #ifdef _DEBUG
  377.         // assert(FALSE);
  378. #endif
  379.       }
  380.       if (meth) {
  381.         /* Flush headers */
  382.         length = buffer_size - 2;
  383.         while(linputsoc_t(soc_c, line, sizeof(line) - 2, timeout) > 0) {
  384.           int p;
  385.           if ((p=strfield(line,"Content-length:"))!=0) {
  386.             sscanf(line+p, LLintP, &(length));
  387.           }
  388.           else if ((p=strfield(line,"Accept-language:"))!=0) {
  389.             char tmp[32];
  390.             char* s = line + p;
  391.             /*int l;*/
  392.             while(*s == ' ') s++;
  393.             tmp[0] = '\0';
  394.             strncatbuff(tmp, s, 2);
  395.             /*l = LANG_SEARCH(path, tmp);*/
  396.           }
  397.         }
  398.         if (meth == 2) {
  399.           int sz = 0;
  400.           if (length > buffer_size - 2) {
  401.             length = buffer_size - 2;
  402.           }
  403.           if (length > 0 && (sz=recv_bl(soc_c, buffer, (int)length, timeout)) < 0) {
  404.             meth = 0;
  405.           } else {
  406.             buffer[sz] = '\0';
  407.           }
  408.         }
  409.       }
  410.  
  411.       /* Generated variables */
  412.       if (commandEnd && !commandReturnSet) {
  413.         commandReturnSet = 1;
  414.         if (commandReturn) {
  415.           char tmp[32];
  416.           sprintf(tmp, "%d", commandReturn);
  417.           inthash_write(NewLangList, "commandReturn", (unsigned long int)strdup(tmp));
  418.           inthash_write(NewLangList, "commandReturnMsg", (unsigned long int)commandReturnMsg);
  419.           inthash_write(NewLangList, "commandReturnCmdl", (unsigned long int)commandReturnCmdl);
  420.         } else {
  421.           inthash_write(NewLangList, "commandReturn", (unsigned long int)NULL);
  422.           inthash_write(NewLangList, "commandReturnMsg", (unsigned long int)NULL);
  423.           inthash_write(NewLangList, "commandReturnCmdl", (unsigned long int)NULL);
  424.         }
  425.       }
  426.  
  427.       /* SID check */
  428.       {
  429.         unsigned long int adr = 0;
  430.         if (inthash_readptr(NewLangList, "_sid", (long int *)&adr)) {
  431.           if (inthash_write(NewLangList, "sid", (unsigned long int)strdup((char*)adr))) {
  432.           }
  433.         }
  434.       }
  435.  
  436.       /* check variables */
  437.       if (meth && buffer[0]) {
  438.         char* s = buffer;
  439.         char *e, *f;
  440.         strcatbuff(buffer, "&");
  441.         while( s && (e = strchr(s, '=')) && (f = strchr(s, '&')) ) {
  442.           char* ua;
  443.           int len;
  444.           String sua = STRING_EMPTY;
  445.           *e = *f = '\0';
  446.           ua = e + 1;
  447.           if (strfield2(ua, "on"))  /* hack : "on" == 1 */
  448.             ua = "1";
  449.           len = strlen(ua);
  450.           unescapehttp(ua, &sua);
  451.           inthash_write(NewLangList, s, (unsigned long int)StringAcquire(&sua));
  452.           s = f + 1;
  453.         }
  454.       }
  455.  
  456.  
  457.       /* Error check */
  458.       {
  459.         unsigned long int adr = 0;
  460.         unsigned long int adr2 = 0;
  461.         if (inthash_readptr(NewLangList, "sid", (long int *)&adr)) {
  462.           if (inthash_readptr(NewLangList, "_sid", (long int *)&adr2)) {
  463.             if (strcmp((char*)adr, (char*)adr2) != 0) {
  464.               meth = 0;
  465.             }
  466.           }
  467.         }
  468.       }
  469.  
  470.       /* Check variables (internal) */
  471.       if (meth) {
  472.         int doLoad=0;
  473.         unsigned long int adr = 0;
  474.         if (inthash_readptr(NewLangList, "lang", (long int *)&adr)) {
  475.           int n = 0;
  476.           if (sscanf((char*)adr, "%d", &n) == 1 && n - 1 != LANG_T(path, -1)) {
  477.             LANG_T(path, n - 1);
  478.           }
  479.         }
  480.  
  481.         /* Load existing project settings */
  482.         if (inthash_readptr(NewLangList, "loadprojname", (long int *)&adr)) {
  483.           char* pname = (char*) adr;
  484.           if (*pname) {
  485.             inthash_write(NewLangList, "projname", (unsigned long int)strdup(pname));
  486.           }
  487.           inthash_write(NewLangList, "loadprojname", (unsigned long int)NULL);
  488.           doLoad=1;
  489.         }
  490.  
  491.         /* path : <path>/<project> */
  492.         if (!commandRunning) {
  493.           unsigned long int adrw = 0, adrpath = 0, adrprojname = 0;
  494.           if (inthash_readptr(NewLangList, "path", (long int *)&adrpath)
  495.             && inthash_readptr(NewLangList, "projname", (long int *)&adrprojname)) {
  496.             StringClear(&fspath);
  497.             StringStrcat(&fspath, (char*)adrpath);
  498.             StringStrcat(&fspath, "/");
  499.             StringStrcat(&fspath, (char*)adrprojname);
  500.           }
  501.         }
  502.         
  503.         /* Load existing project settings */
  504.         if (doLoad) {
  505.           FILE* fp;
  506.           StringStrcat(&fspath, "/hts-cache/winprofile.ini");
  507.           fp = fopen(StringBuff(&fspath), "rb");
  508.           if (fp) {
  509.             /* Read file */
  510.             while(!feof(fp)) {
  511.               char* str = line;
  512.               char* pos;
  513.               if (!linput(fp, line, sizeof(line) - 2)) {
  514.                 *str = '\0';
  515.               }
  516.               pos=strchr(line, '=');
  517.               if (pos) {
  518.                 String escline = STRING_EMPTY;
  519.                 *pos++='\0';
  520.                 if (pos[0] == '0' && pos[1] == '\0')
  521.                   *pos = '\0';   /* 0 => empty */
  522.                 unescapeini(pos, &escline);
  523.                 inthash_write(NewLangList, line, (unsigned long int)StringAcquire(&escline));
  524.               }
  525.             }
  526.             
  527.             fclose(fp);
  528.           }
  529.         }
  530.         
  531.       }
  532.  
  533.       /* Execute command */
  534.       {
  535.         unsigned long int adr = 0;
  536.         int p = 0;
  537.         if (inthash_readptr(NewLangList, "command", (long int *)&adr)) {
  538.           if (strcmp((char*)adr, "cancel") == 0) {
  539.             if (commandRunning) {
  540.               if (!commandEndRequested) {
  541.                 commandEndRequested=1;
  542.                 hts_request_stop(0);
  543.               } else {
  544.                 hts_request_stop(1);   /* note: the force flag does not have anyeffect yet */
  545.                 commandEndRequested=2; /* will break the loop() callback */
  546.               }
  547.             }
  548.           } else if ((p=strfield((char*)adr, "cancel-file="))) {
  549.             if (commandRunning) {
  550.               hts_cancel_file((char*)adr + p);
  551.             }
  552.           } else if (strcmp((char*)adr, "cancel-parsing") == 0) {
  553.             if (commandRunning) {
  554.               hts_cancel_parsing();
  555.             }
  556.           } else if ((p=strfield((char*)adr, "pause="))) {
  557.             if (commandRunning) {
  558.               hts_setpause(1);
  559.             }
  560.           } else if ((p=strfield((char*)adr, "unpause"))) {
  561.             if (commandRunning) {
  562.               hts_setpause(0);
  563.             }
  564.           } else if (strcmp((char*)adr, "abort") == 0) {
  565.             if (commandRunning) {
  566.               hts_request_stop(1);
  567.               commandEndRequested=2; /* will break the loop() callback */
  568.             }
  569.           } else if ((p=strfield((char*)adr, "add-url="))) {
  570.             if (commandRunning) {
  571.               char* ptraddr[2];
  572.               ptraddr[0] = (char*)adr + p;
  573.               ptraddr[1] = NULL;
  574.               hts_addurl(ptraddr);
  575.             }
  576.           } else if ((p=strfield((char*)adr, "httrack"))) {
  577.             if (!commandRunning) {
  578.               unsigned long int adrcd = 0;
  579.               if (inthash_readptr(NewLangList, "command_do", (long int *)&adrcd)) {
  580.                 unsigned long int adrw = 0, adrpath = 0, adrprojname = 0;
  581.                 if (inthash_readptr(NewLangList, "winprofile", (long int *)&adrw)) {
  582.                   StringClear(&tmpbuff);
  583.                   StringStrcat(&tmpbuff, StringBuff(&fspath));
  584.                   StringStrcat(&tmpbuff, "/hts-cache/");
  585.                   
  586.                   /* Create minimal directory structure */
  587.                   if (!structcheck(StringBuff(&tmpbuff))) {
  588.                     FILE* fp;
  589.                     StringStrcat(&tmpbuff, "winprofile.ini");
  590.                     fp = fopen(StringBuff(&tmpbuff), "wb");
  591.                     if (fp != NULL) {
  592.                       int count = (int) strlen((char*)adrw);
  593.                       if ((int)fwrite((void*)adrw, 1, count, fp) == count) {
  594.                         
  595.                       /* Wipe the doit.log file, useless here (all options are replicated) and
  596.                       even a bit annoying (duplicate/ghost options)
  597.                       The behaviour is exactly the same as in WinHTTrack
  598.                         */
  599.                         StringClear(&tmpbuff);
  600.                         StringStrcat(&tmpbuff, StringBuff(&fspath));
  601.                         StringStrcat(&tmpbuff, "/hts-cache/doit.log");
  602.                         remove(StringBuff(&tmpbuff));
  603.                         
  604.                         /*
  605.                         RUN THE SERVER
  606.                         */
  607.                         if (strcmp((char*)adrcd, "start") == 0) {
  608.                           webhttrack_main((char*)adr + p);
  609.                         } else {
  610.                           commandRunning = 0;
  611.                           commandEnd = 1;
  612.                         }
  613.                       } else {
  614.                         char tmp[1024];
  615.                         sprintf(tmp, "Unable to write %d bytes in the the init file %s", count, StringBuff(&fspath));
  616.                         SET_ERROR(tmp);
  617.                       }
  618.                       fclose(fp);
  619.                     } else {
  620.                       char tmp[1024];
  621.                       sprintf(tmp, "Unable to create the init file %s", StringBuff(&fspath));
  622.                       SET_ERROR(tmp);
  623.                     }
  624.                   } else {
  625.                     char tmp[1024];
  626.                     sprintf(tmp, "Unable to create the directory structure in %s", StringBuff(&fspath));
  627.                     SET_ERROR(tmp);
  628.                   }
  629.                   
  630.                 } else {
  631.                   SET_ERROR("Internal server error: unable to fetch project name or path");
  632.                 }
  633.               }
  634.             }
  635.           } else if (strcmp((char*)adr, "quit") == 0) {
  636.             willexit=1;
  637.           }
  638.           inthash_write(NewLangList, "command", (unsigned long int)NULL);
  639.         }
  640.       }
  641.  
  642.       /* Response */
  643.       if (meth) {
  644.         int virtualpath = 0;
  645.         char* pos;
  646.         char* url = strchr(line1, ' ');
  647.         if (url && *++url == '/' && (pos = strchr(url, ' ')) && !(*pos = '\0') ) {
  648.           char fsfile[1024];
  649.           char* file;
  650.           FILE* fp;
  651.           char* qpos;
  652.  
  653.           /* get the URL */
  654.           if (error_redirect == NULL) {
  655.             if ( (qpos = strchr(url, '?')) ) {
  656.               *qpos = '\0';
  657.             }
  658.             fsfile[0] = '\0';
  659.             if (strcmp(url, "/") == 0) {
  660.               file = "/server/index.html";
  661.               meth = 2;
  662.             } else {
  663.               file = url;
  664.             }
  665.           } else {
  666.             file = error_redirect;
  667.             meth = 2;
  668.           }
  669.           
  670.           if (strncmp(file, "/website/", 9) == 0) {
  671.             virtualpath = 1;
  672.           }
  673.  
  674.           if (commandRunning) {
  675.             if (!is_image(file)) {
  676.               file = "/server/refresh.html";
  677.             }
  678.           } else if (commandEnd && !virtualpath && !willexit) {
  679.             if (!is_image(file)) {
  680.               file = "/server/finished.html";
  681.             }
  682.           }
  683.           
  684.           if (strlen(path) + strlen(file) + 32 < sizeof(fsfile)) {
  685.             if (strncmp(file, "/website/", 9) != 0) {
  686.               sprintf(fsfile, "%shtml%s", path, file);
  687.             } else {
  688.               unsigned long int adr = 0;
  689.               if (inthash_readptr(NewLangList, "projpath", (long int *)&adr)) {
  690.                 sprintf(fsfile, "%s%s", (char*)adr, file + 9);
  691.               }
  692.             }
  693.           }
  694.           
  695.           if (fsfile[0] && strstr(file, "..") == NULL && (fp = fopen(fsfile, "rb"))) {
  696.             char ok[] = "HTTP/1.0 200 OK\r\n"
  697.               "Connection: close\r\n"
  698.               "Server: httrack-small-server\r\n"
  699.               "Content-type: text/html\r\n"
  700.               "Cache-Control: no-cache, must-revalidate, private\r\n"
  701.               "Pragma: no-cache\r\n"
  702.               ;
  703.             char ok_img[] = "HTTP/1.0 200 OK\r\n"
  704.               "Connection: close\r\n"
  705.               "Server: httrack small server\r\n"
  706.               "Content-type: image/gif\r\n"
  707.               ;
  708.             char ok_text[] = "HTTP/1.0 200 OK\r\n"
  709.               "Connection: close\r\n"
  710.               "Server: httrack small server\r\n"
  711.               "Content-type: text/plain\r\n"
  712.               ;
  713.  
  714.             /* register current page */
  715.             inthash_write(NewLangList, "thisfile", (unsigned long int)strdup(file));
  716.  
  717.             /* Force GET for the last request */
  718.             if (meth == 2 && willexit) {
  719.               meth = 1;
  720.             }
  721.  
  722.             /* posted data are redirected to get protocol */
  723.             if (meth == 2) {
  724.               char redir[] = "HTTP/1.0 302 Redirect\r\n"
  725.                 "Connection: close\r\n"
  726.                 "Server: httrack-small-server\r\n";
  727.               unsigned long int adr = 0;
  728.               char* newfile = file;
  729.               if (inthash_readptr(NewLangList, "redirect", (long int *)&adr) && adr != 0) {
  730.                 char* newadr = (char*)adr;
  731.                 if (*newadr) {
  732.                   newfile = newadr;
  733.                 }
  734.               }
  735.               StringMemcat(&headers, redir, strlen(redir));
  736.               {
  737.                 char tmp[256];
  738.                 if (strlen(file) < sizeof(tmp) - 32) {
  739.                   sprintf(tmp, "Location: %s\r\n", newfile);
  740.                   StringMemcat(&headers, tmp, strlen(tmp));
  741.                 }
  742.               }
  743.               inthash_write(NewLangList, "redirect", (unsigned long int)NULL);
  744.             }
  745.             else if (is_html(file)) {
  746.               int outputmode = 0;
  747.               StringMemcat(&headers, ok, sizeof(ok) - 1);
  748.               while(!feof(fp)) {
  749.                 char* str = line;
  750.                 int prevlen = StringLength(&output);
  751.                 int nocr = 0;
  752.                 if (!linput(fp, line, sizeof(line) - 2)) {
  753.                   *str = '\0';
  754.                 }
  755.                 if (*str && str[strlen(str) - 1] == '\\') {
  756.                   nocr = 1;
  757.                   str[strlen(str) - 1] = '\0';
  758.                 }
  759.                 while(*str) {
  760.                   char* pos;
  761.                   int n;
  762.                   if (*str == '$' && *++str == '{' && (pos = strchr(++str, '}')) && (n = (pos - str) ) && n < 1024 ) {
  763.                     char name_[1024 + 2];
  764.                     char* name = name_;
  765.                     char* langstr = NULL;
  766.                     int p;
  767.                     int format = 0;
  768.                     int listDefault = 0;
  769.                     name[0] = '\0';
  770.                     strncatbuff(name, str, n);
  771.                     if (strncmp(name, "/*", 2) == 0) {
  772.                       /* comments */
  773.                     }
  774.                     else if (( p = strfield(name, "html:"))) {
  775.                       name += p;
  776.                       format = 1;
  777.                     }
  778.                     else if (( p = strfield(name, "list:"))) {
  779.                       name += p;
  780.                       format = 2;
  781.                     }
  782.                     else if (( p = strfield(name, "liststr:"))) {
  783.                       name += p;
  784.                       format = -2;
  785.                     }
  786.                     else if (( p = strfield(name, "file-exists:"))) {
  787.                       char* pos2;
  788.                       name += p;
  789.                       format = 0;
  790.                       pos2 = strchr(name, ':');
  791.                       langstr = "";
  792.                       if (pos2 != NULL) {
  793.                         *pos2 = '\0';
  794.                         if (strstr(name, "..") == NULL) {
  795.                           if (fexist(fconcat(path, name))) {
  796.                             langstr = pos2 + 1;
  797.                           }
  798.                         }
  799.                       }
  800.                     }
  801.                     else if (( p = strfield(name, "do:"))) {
  802.                       char* pos2;
  803.                       name += p;
  804.                       format = 1;
  805.                       pos2 = strchr(name, ':');
  806.                       langstr = "";
  807.                       if (pos2 != NULL) {
  808.                         *pos2 = '\0';
  809.                         pos2++;
  810.                       } else {
  811.                         pos2="";
  812.                       }
  813.                       if (strcmp(name, "output-mode") == 0) {
  814.                         if (strcmp(pos2, "html") == 0) {
  815.                           outputmode = 1;
  816.                         } else if (strcmp(pos2, "inifile") == 0) {
  817.                           outputmode = 2;                         
  818.                         } else if (strcmp(pos2, "html-urlescaped") == 0) {
  819.                           outputmode = 3;                         
  820.                         } else {
  821.                           outputmode = 0;
  822.                         }
  823.                       } else if (strcmp(name, "if-file-exists") == 0) {
  824.                         if (strstr(pos2, "..") == NULL) {
  825.                           if (!fexist(fconcat(path, pos2))) {
  826.                             outputmode = -1;
  827.                           }
  828.                         }
  829.                       } else if (strcmp(name, "if-project-file-exists") == 0) {
  830.                         if (strstr(pos2, "..") == NULL) {
  831.                           if (!fexist(fconcat(StringBuff(&fspath), pos2))) {
  832.                             outputmode = -1;
  833.                           }
  834.                         }
  835.                       } else if (strcmp(name, "if-file-do-not-exists") == 0) {
  836.                         if (strstr(pos2, "..") == NULL) {
  837.                           if (fexist(fconcat(path, pos2))) {
  838.                             outputmode = -1;
  839.                           }
  840.                         }
  841.                       } else if (strcmp(name, "if-not-empty") == 0) {
  842.                         unsigned long int adr = 0;
  843.                         if (!inthash_readptr(NewLangList, pos2, (long int *)&adr) || *((char*)adr) == 0 ) {
  844.                           outputmode = -1;
  845.                         }
  846.                       } else if (strcmp(name, "if-empty") == 0) {
  847.                         unsigned long int adr = 0;
  848.                         if (inthash_readptr(NewLangList, pos2, (long int *)&adr) && *((char*)adr) != 0 ) {
  849.                           outputmode = -1;
  850.                         }
  851.                       } else if (strcmp(name, "end-if") == 0) {
  852.                         outputmode = 0;
  853.                       } else if (strcmp(name, "loadhash") == 0) {
  854.                         unsigned long int adr = 0;
  855.                         if (inthash_readptr(NewLangList, "path", (long int *)&adr)) {
  856.                           char* rpath = (char*) adr;
  857.                           find_handle h;
  858.                           if (rpath[0]) {
  859.                             if (rpath[strlen(rpath)-1]=='/') {
  860.                               rpath[strlen(rpath)-1]='\0';      /* note: patching stored (inhash) value */
  861.                             }
  862.                           }
  863.                           h = hts_findfirst(rpath);
  864.                           if (h) {
  865.                             struct topindex_chain * chain=NULL;
  866.                             struct topindex_chain * startchain=NULL;
  867.                             StringClear(&tmpbuff);
  868.                             do {
  869.                               if (hts_findisdir(h)) {
  870.                                 char iname[HTS_URLMAXSIZE*2];
  871.                                 strcpybuff(iname,rpath);
  872.                                 strcatbuff(iname,"/");
  873.                                 strcatbuff(iname,hts_findgetname(h));
  874.                                 strcatbuff(iname,"/hts-cache/winprofile.ini");
  875.                                 if (fexist(iname)) {
  876.                                   if (StringLength(&tmpbuff) > 0) {
  877.                                     StringStrcat(&tmpbuff, "\r\n");
  878.                                   }
  879.                                   StringStrcat(&tmpbuff, hts_findgetname(h));
  880.                                 }
  881.                                 
  882.                               }
  883.                             } while(hts_findnext(h));
  884.                             hts_findclose(h);
  885.                             inthash_write(NewLangList, "winprofile", (unsigned long int)StringAcquire(&tmpbuff));
  886.                           }
  887.                         }  
  888.                       } else if (strcmp(name, "copy") == 0) {
  889.                         if (*pos2) {
  890.                           char* pos3 = strchr(pos2, ':');
  891.                           if ( pos3 && *(pos3 + 1) ) {
  892.                             unsigned long int adr = 0;
  893.                             *pos3++ = '\0';
  894.                             if (inthash_readptr(NewLangList, pos2, (long int *)&adr)) {
  895.                               inthash_write(NewLangList, pos3, (unsigned long int)strdup((char*)adr));
  896.                               inthash_write(NewLangList, pos2, (unsigned long int)NULL);
  897.                             }
  898.                           }
  899.                         }
  900.                       } else if (strcmp(name, "set") == 0) {
  901.                         if (*pos2) {
  902.                           char* pos3 = strchr(pos2, ':');
  903.                           if ( pos3 ) {
  904.                             *pos3++ = '\0';
  905.                             inthash_write(NewLangList, pos2, (unsigned long int)strdup(pos3));
  906.                           } else {
  907.                             inthash_write(NewLangList, pos2, (unsigned long int)NULL);
  908.                           }
  909.                         }
  910.                       }
  911.                     }
  912.                     /*
  913.                     test:<if exist>
  914.                     test:<if ==0>:<if ==1>:<if == 2>..
  915.                     ztest:<if == 0 || !exist>:<if == 1>:<if == 2>..
  916.                     */
  917.                     else if ( ( p = strfield(name, "test:")) || ( p = strfield(name, "ztest:")) ) {
  918.                       unsigned long int adr = 0;
  919.                       char* pos2;
  920.                       int ztest = (name[0] == 'z');
  921.                       langstr = "";
  922.                       name += p;
  923.                       pos2 = strchr(name, ':');
  924.                       if (pos2 != NULL) {
  925.                         *pos2 = '\0';
  926.                         if (inthash_readptr(NewLangList, name, (long int *)&adr) || ztest) {
  927.                           char* newadr = (char*)adr;
  928.                           if (!newadr)
  929.                             newadr = "";
  930.                           if (*newadr || ztest) {
  931.                             int npos = 0;
  932.                             name = pos2 + 1;
  933.                             format = 4;
  934.                             if (strchr(name, ':') == NULL) {
  935.                               npos = 0;  /* first is good if only one : */
  936.                               format = 0;
  937.                             } else {
  938.                               if (sscanf(newadr, "%d", &npos) != 1) {
  939.                                 if (strfield(newadr, "on")) {
  940.                                   npos = 1;
  941.                                 } else {
  942.                                   npos = 0;   /* first one will be ok */
  943.                                   format = 0;
  944.                                 }
  945.                               }
  946.                             }
  947.                             while( *name && *name != '}' && npos >= 0) {
  948.                               int end=0;
  949.                               char* fpos = strchr(name, ':');
  950.                               int n2;
  951.                               if (fpos == NULL) {
  952.                                 fpos = name + strlen(name);
  953.                                 end=1;
  954.                               }
  955.                               n2 = (int) (fpos - name);
  956.                               if (npos == 0) {
  957.                                 langstr = name;
  958.                                 *fpos='\0';
  959.                               } else if (end) {
  960.                                 npos=0;
  961.                               }
  962.                               name += n2 + 1;
  963.                               npos--;
  964.                             }
  965.                           }
  966.                         }
  967.                       }
  968.                     }
  969.                     else if (( p = strfield(name, "listid:"))) {
  970.                       char* pos2;
  971.                       name += p;
  972.                       format = 2;
  973.                       pos2 = strchr(name, ':');
  974.                       if (pos2) {
  975.                         char dname[32];
  976.                         int n2 = (int) (pos2 - name);
  977.                         if (n2 > 0 && n2 < sizeof(dname) - 2) {
  978.                           unsigned long int adr = 0;
  979.                           dname[0] = '\0';
  980.                           strncatbuff(dname, name, n2);
  981.                           if (inthash_readptr(NewLangList, dname, (long int *)&adr)) {
  982.                             int n = 0;
  983.                             if (sscanf((char*)adr, "%d", &n) == 1) {
  984.                               listDefault = n;
  985.                             }
  986.                           }
  987.                           name += n2 + 1;
  988.                         }
  989.                       }
  990.                     }
  991.                     else if (( p = strfield(name, "checked:"))) {
  992.                       name += p;
  993.                       format = 3;
  994.                     }
  995.                     if (langstr == NULL) {
  996.                       if (strfield2(name, "#iso")) {
  997.                         langstr = line2;
  998.                         langstr[0] = '\0';
  999.                         LANG_LIST(path, langstr);
  1000.                         assertf(strlen(langstr) < sizeof(line2) - 2);
  1001.                       } else {
  1002.                         langstr = LANGSEL(name);
  1003.                         if (langstr == NULL || *langstr == '\0') {
  1004.                           unsigned long int adr = 0;
  1005.                           if (inthash_readptr(NewLangList, name, (long int *)&adr)) {
  1006.                             char* newadr = (char*)adr;
  1007.                             langstr = newadr;
  1008.                           }
  1009.                         }
  1010.                       }
  1011.                     }
  1012.                     if (langstr && outputmode != -1) {
  1013.                       switch(format) {
  1014.                       case 0:
  1015.                         {
  1016.                           char* a = langstr;
  1017.                           while(*a) {
  1018.                             if (a[0] == '\\' && isxdigit(a[1]) && isxdigit(a[2])) {
  1019.                               int n;
  1020.                               char c;
  1021.                               if (sscanf(a+1, "%x", &n) == 1) {
  1022.                                 c = (char)n;
  1023.                                 StringMemcat(&output, &c, 1);
  1024.                               }
  1025.                               a += 2;
  1026.                             } else if (outputmode && a[0] == '<') {
  1027.                               StringStrcat(&output, "<");
  1028.                             } else if (outputmode && a[0] == '>') {
  1029.                               StringStrcat(&output, ">");
  1030.                             } else if (outputmode && a[0] == '&') {
  1031.                               StringStrcat(&output, "&");
  1032.                             } else if (outputmode == 3 && a[0] == ' ') {
  1033.                               StringStrcat(&output, "%20");
  1034.                             } else if (outputmode >= 2 && ((unsigned char)a[0]) < 32) {
  1035.                               char tmp[32];
  1036.                               sprintf(tmp, "%%%02x", (unsigned char)a[0]);
  1037.                               StringStrcat(&output, tmp);
  1038.                             } else if (outputmode == 2 && a[0] == '%') {
  1039.                               StringStrcat(&output, "%%");
  1040.                             } else if (outputmode == 3 && a[0] == '%') {
  1041.                               StringStrcat(&output, "%25");
  1042.                             } else {
  1043.                               StringMemcat(&output, a, 1);
  1044.                             }
  1045.                             a++;
  1046.                           }
  1047.                         }
  1048.                         break;
  1049.                       case 3:
  1050.                         if (*langstr) {
  1051.                           StringStrcat(&output, "checked");
  1052.                         }
  1053.                         break;
  1054.                       default: 
  1055.                         if (*langstr) {
  1056.                           int id=1;
  1057.                           char* fstr = langstr;
  1058.                           StringClear(&tmpbuff);
  1059.                           if (format == 2) {
  1060.                             StringStrcat(&output, "<option value=1>");
  1061.                           } else if (format == -2) {
  1062.                             StringStrcat(&output, "<option value=\"");
  1063.                           }
  1064.                           while(*fstr) {
  1065.                             switch(*fstr) {
  1066.                             case 13: break;
  1067.                             case 10:
  1068.                               if (format == 1) {
  1069.                                 StringStrcat(&output, StringBuff(&tmpbuff));
  1070.                                 StringStrcat(&output, "<br>\r\n");
  1071.                               } else if (format == -2) {
  1072.                                 StringStrcat(&output, StringBuff(&tmpbuff));
  1073.                                 StringStrcat(&output, "\">");
  1074.                                 StringStrcat(&output, StringBuff(&tmpbuff));
  1075.                                 StringStrcat(&output, "</option>\r\n");
  1076.                                 StringStrcat(&output, "<option value=\"");
  1077.                               } else {
  1078.                                 char tmp[32];
  1079.                                 sprintf(tmp, "%d", ++id);
  1080.                                 StringStrcat(&output, StringBuff(&tmpbuff));
  1081.                                 StringStrcat(&output, "</option>\r\n");
  1082.                                 StringStrcat(&output, "<option value=");
  1083.                                 StringStrcat(&output, tmp);
  1084.                                 if (listDefault == id) {
  1085.                                   StringStrcat(&output, " selected");
  1086.                                 }
  1087.                                 StringStrcat(&output, ">");
  1088.                               }
  1089.                               StringClear(&tmpbuff);
  1090.                               break;
  1091.                             case '<':
  1092.                               StringStrcat(&tmpbuff, "<");
  1093.                               break;
  1094.                             case '>':
  1095.                               StringStrcat(&tmpbuff, ">");
  1096.                               break;
  1097.                             case '&':
  1098.                               StringStrcat(&tmpbuff, "&");
  1099.                               break;
  1100.                             default:
  1101.                               StringMemcat(&tmpbuff, fstr, 1);
  1102.                               break;
  1103.                             }
  1104.                             fstr++;
  1105.                           }
  1106.                           if (format == 2) {
  1107.                             StringStrcat(&output, StringBuff(&tmpbuff));
  1108.                             StringStrcat(&output, "</option>");
  1109.                           } else if (format == -2) {
  1110.                             StringStrcat(&output, StringBuff(&tmpbuff));
  1111.                             StringStrcat(&output, "\">");
  1112.                             StringStrcat(&output, StringBuff(&tmpbuff));
  1113.                             StringStrcat(&output, "</option>");
  1114.                           } else {
  1115.                             StringStrcat(&output, StringBuff(&tmpbuff));
  1116.                           }
  1117.                           StringClear(&tmpbuff);
  1118.                         }
  1119.                       }
  1120.                     }
  1121.                     str = pos;
  1122.                   } else {
  1123.                     if (outputmode != -1) {
  1124.                       StringMemcat(&output, str, 1);
  1125.                     }
  1126.                   }
  1127.                   str++;
  1128.                 }
  1129.                 if (!nocr && prevlen != StringLength(&output)) {
  1130.                   StringStrcat(&output, "\r\n");
  1131.                 }
  1132.               }
  1133. #ifdef _DEBUG
  1134.               {
  1135.                 int len = (int)strlen((char*)StringBuff(&output));
  1136.                 assert(len == (int)StringLength(&output));
  1137.               }
  1138. #endif
  1139.             } else if (is_text(file)) {
  1140.               StringMemcat(&headers, ok_text, sizeof(ok_text) - 1);
  1141.               while(!feof(fp)) {
  1142.                 int n = fread(line, 1, sizeof(line) - 2, fp);
  1143.                 if (n > 0) {
  1144.                   StringMemcat(&output, line, n);
  1145.                 }
  1146.               }
  1147.             } else {
  1148.               StringMemcat(&headers, ok_img, sizeof(ok_img) - 1);
  1149.               while(!feof(fp)) {
  1150.                 int n = fread(line, 1, sizeof(line) - 2, fp);
  1151.                 if (n > 0) {
  1152.                   StringMemcat(&output, line, n);
  1153.                 }
  1154.               }
  1155.             }
  1156.             fclose(fp);
  1157.           } else {
  1158.             char error_hdr[] = "HTTP/1.0 404 Not Found\r\n"
  1159.               "Server: httrack small server\r\n"
  1160.               "Content-type: text/html\r\n";
  1161.             char error[] = 
  1162.               "Page not found.\r\n";
  1163.             StringStrcat(&headers, error_hdr);
  1164.             StringStrcat(&output, error);
  1165.             //assert(file == NULL);
  1166.           }
  1167.         }
  1168.       } else {
  1169. #ifdef _DEBUG
  1170.         char error_hdr[] = "HTTP/1.0 500 Server Error\r\n"
  1171.           "Server: httrack small server\r\n"
  1172.           "Content-type: text/html\r\n";
  1173.         char error[] = 
  1174.           "Server error.\r\n";
  1175.         StringStrcat(&headers, error_hdr);
  1176.         StringStrcat(&output, error);
  1177. #endif
  1178.       }
  1179.       {
  1180.         char tmp[256];
  1181.         sprintf(tmp, "Content-length: %d\r\n", (int) StringLength(&output));
  1182.         StringStrcat(&headers, tmp);
  1183.       }
  1184.       StringStrcat(&headers, "\r\n");
  1185.       if (
  1186.           (send(soc_c, StringBuff(&headers), StringLength(&headers), 0) != StringLength(&headers))
  1187.           ||
  1188.           ( (meth == 1) && (send(soc_c, StringBuff(&output), StringLength(&output), 0) != StringLength(&output)) )
  1189.         ) {
  1190. #ifdef _DEBUG
  1191.         //assert(FALSE);
  1192. #endif
  1193.       }
  1194.     } else {
  1195. #ifdef _DEBUG
  1196.       // assert(FALSE);
  1197. #endif
  1198.     }
  1199.     
  1200.     /* Shutdown (FIN) and wait until confirmed */
  1201.     {
  1202.       char c;
  1203. #ifdef _WIN32
  1204.       shutdown(soc_c, SD_SEND);
  1205. #else
  1206.       shutdown(soc_c, 1);
  1207. #endif
  1208.       /* This is necessary as IE sometimes (!) sends an additional CRLF after POST data */
  1209.       while(recv(soc_c, ((char*)&c), 1, 0) > 0);
  1210.     }
  1211.  
  1212. #if HTS_WIN
  1213.     closesocket(soc_c);
  1214. #else
  1215.     close(soc_c);
  1216. #endif
  1217.   }
  1218.  
  1219.   if (soc != INVALID_SOCKET) {
  1220. #ifdef _WIN32
  1221.     closesocket(soc);
  1222. #else
  1223.     close(soc);
  1224. #endif
  1225.   }
  1226.  
  1227.   StringFree(&headers);
  1228.   StringFree(&output);
  1229.   StringFree(&tmpbuff);
  1230.   StringFree(&fspath);
  1231.  
  1232.   if (buffer)
  1233.     free(buffer);
  1234.  
  1235.   if (commandReturnMsg)
  1236.     free(commandReturnMsg);
  1237.   commandReturnMsg = NULL;
  1238.   if (commandReturnCmdl)
  1239.     free(commandReturnCmdl);
  1240.   commandReturnCmdl = NULL;
  1241.  
  1242.   /* Unlock */
  1243.   webhttrack_lock(0);
  1244.  
  1245.   return retour;
  1246. }
  1247.  
  1248.  
  1249.  
  1250. /* Language files */
  1251.  
  1252.  
  1253. int htslang_init() {
  1254.   if (NewLangList==NULL) {
  1255.     int i = 0;
  1256.     NewLangList=inthash_new(NewLangListSz);
  1257.     if (NewLangList==NULL) {
  1258.       abortLog("Error in lang.h: not enough memory");
  1259.     } else {
  1260.       inthash_value_is_malloc(NewLangList,1);
  1261.     }
  1262.   }
  1263.   return 1;
  1264. }
  1265.  
  1266. int htslang_uninit() {
  1267.   if (NewLangList!=NULL) {
  1268.     inthash_delete(&NewLangList);
  1269.   }
  1270.   return 1;
  1271. }
  1272.  
  1273. int htslang_load(char* limit_to, char* path) {
  1274.   char* hashname;
  1275.   //
  1276.   int selected_lang=LANG_T(path, -1);
  1277.   //
  1278.   if (!limit_to) {
  1279.     LANG_DELETE();
  1280.     NewLangStr=inthash_new(NewLangStrSz);
  1281.     NewLangStrKeys=inthash_new(NewLangStrKeysSz);
  1282.     if ((NewLangStr==NULL) || (NewLangStrKeys==NULL)) {
  1283.       abortLog("Error in lang.h: not enough memory");
  1284.     } else {
  1285.       inthash_value_is_malloc(NewLangStr,1);
  1286.       inthash_value_is_malloc(NewLangStrKeys,1);
  1287.     }
  1288.   }
  1289.  
  1290.   /* Load master file (list of keys and internal keys) */
  1291.   if (!limit_to) {
  1292.     char* mname = "lang.def";
  1293.     FILE* fp=fopen(fconcat(path, mname),"rb");
  1294.     if (fp) {
  1295.       char intkey[8192];
  1296.       char key[8192];
  1297.       while(!feof(fp)) {
  1298.         linput_cpp(fp,intkey,8000);
  1299.         linput_cpp(fp,key,8000);
  1300.         if (strnotempty(intkey) && strnotempty(key)) {
  1301.           char* test=LANGINTKEY(key);
  1302.  
  1303.           /* Increment for multiple definitions */
  1304.           if (strnotempty(test)) {
  1305.             int increment=0;
  1306.             int pos=strlen(key);
  1307.             do {
  1308.               increment++;
  1309.               sprintf(key+pos,"%d",increment);
  1310.               test=LANGINTKEY(key);
  1311.             }  while (strnotempty(test));
  1312.           }
  1313.  
  1314.           if (!strnotempty(test)) {         // Θviter doublons
  1315.             // conv_printf(key,key);
  1316.             int len;
  1317.             char* buff;
  1318.             len=strlen(intkey);
  1319.             buff=(char*)malloc(len+2);
  1320.             if (buff) {
  1321.               strcpybuff(buff,intkey);
  1322.               inthash_add(NewLangStrKeys,key,(long int)(char*)buff);
  1323.             }
  1324.           }
  1325.         } // if
  1326.       }  // while
  1327.       fclose(fp);
  1328.     } else {
  1329.       return 0;
  1330.     }
  1331.   }
  1332.   
  1333.   /* Language Name? */
  1334.   {
  1335.     char name[256];
  1336.     sprintf(name,"LANGUAGE_%d",selected_lang+1);
  1337.     hashname=LANGINTKEY(name);
  1338.   }
  1339.  
  1340.   /* Get only language name */
  1341.   if (limit_to) {
  1342.     if (hashname)
  1343.       strcpybuff(limit_to, hashname);
  1344.     else
  1345.       strcpybuff(limit_to, "???");
  1346.     return 0;
  1347.   }
  1348.  
  1349.   /* Error */
  1350.   if (!hashname)
  1351.     return 0;
  1352.  
  1353.   /* Load specific language file */
  1354.   {
  1355.     int loops;
  1356.     // 2nd loop: load undefined strings
  1357.     for(loops=0;loops<2;loops++) {
  1358.       FILE* fp;
  1359.       char lbasename[1024];
  1360.       {
  1361.         char name[256];
  1362.         sprintf(name,"LANGUAGE_%d",(loops==0)?(selected_lang+1):1);
  1363.         hashname=LANGINTKEY(name);
  1364.       }
  1365.       sprintf(lbasename, "lang/%s.txt",hashname);
  1366.       fp=fopen(fconcat(path, lbasename), "rb");
  1367.       if (fp) {
  1368.         char extkey[8192];
  1369.         char value[8192];
  1370.         while(!feof(fp)) {
  1371.           linput_cpp(fp,extkey,8000);
  1372.           linput_cpp(fp,value,8000);
  1373.           if (strnotempty(extkey) && strnotempty(value)) {
  1374.             int len;
  1375.             char* buff;
  1376.             char* intkey;
  1377.             
  1378.             intkey=LANGINTKEY(extkey);
  1379.             
  1380.             if (strnotempty(intkey)) {
  1381.               
  1382.               /* Increment for multiple definitions */
  1383.               {
  1384.                 char* test=LANGSEL(intkey);
  1385.                 if (strnotempty(test)) {
  1386.                   if (loops == 0) {
  1387.                     int increment=0;
  1388.                     int pos=strlen(extkey);
  1389.                     do {
  1390.                       increment++;
  1391.                       sprintf(extkey+pos,"%d",increment);
  1392.                       intkey=LANGINTKEY(extkey);
  1393.                       if (strnotempty(intkey))
  1394.                         test=LANGSEL(intkey);
  1395.                       else
  1396.                         test="";
  1397.                     }  while (strnotempty(test));
  1398.                   } else
  1399.                     intkey="";
  1400.                 } else {
  1401.                   if (loops > 0) {
  1402.                     //err_msg += intkey;
  1403.                     //err_msg += " ";
  1404.                   }
  1405.                 }
  1406.               }
  1407.               
  1408.               /* Add key */
  1409.               if (strnotempty(intkey)) {
  1410.                 len=strlen(value);
  1411.                 buff=(char*)malloc(len+2);
  1412.                 if (buff) {
  1413.                   conv_printf(value,buff);
  1414.                   inthash_add(NewLangStr,intkey,(long int)(char*)buff);
  1415.                 }
  1416.               }
  1417.               
  1418.             }
  1419.           } // if
  1420.         }  // while
  1421.         fclose(fp);
  1422.       } else {
  1423.         return 0;
  1424.       }
  1425.     }
  1426.   }
  1427.  
  1428.   // Control limit_to
  1429.   if (limit_to)
  1430.     limit_to[0]='\0';
  1431.  
  1432.   return 1;
  1433. }
  1434.  
  1435. /* NOTE : also contains the "webhttrack" hack */
  1436. void conv_printf(char* from,char* to) {
  1437.   int i=0,j=0,len;
  1438.   len=strlen(from);
  1439.   while(i<len) {
  1440.     switch(from[i]) {
  1441.     case '\\': 
  1442.       i++;
  1443.       switch(from[i]) {
  1444.       case 'a': to[j]='\a'; break;
  1445.       case 'b': to[j]='\b'; break;
  1446.       case 'f': to[j]='\f'; break;
  1447.       case 'n': to[j]='\n'; break;
  1448.       case 'r': to[j]='\r'; break;
  1449.       case 't': to[j]='\t'; break;
  1450.       case 'v': to[j]='\v'; break;
  1451.       case '\'': to[j]='\''; break;
  1452.       case '\"': to[j]='\"'; break;
  1453.       case '\\': to[j]='\\'; break;
  1454.       case '?': to[j]='\?'; break;
  1455.       default: to[j]=from[i]; break;
  1456.       }
  1457.       break;
  1458.       default: 
  1459.         to[j]=from[i]; 
  1460.         break;
  1461.     }
  1462.     i++;
  1463.     j++;
  1464.   }
  1465.   to[j++]='\0';
  1466.   /* Dirty hack */
  1467.   {
  1468.     char * a = to;
  1469.     while((a = strstr(a, "WinHTTrack"))) {
  1470.       a[0] = 'W';
  1471.       a[1] = 'e';
  1472.       a[2] = 'b';
  1473.       a++;
  1474.     }
  1475.   }
  1476. }
  1477.  
  1478. void LANG_DELETE() {
  1479.   inthash_delete(&NewLangStr);
  1480.   inthash_delete(&NewLangStrKeys);
  1481. }
  1482.  
  1483. // sΘlection de la langue
  1484. void LANG_INIT(char* path) {
  1485.   //CWinApp* pApp = AfxGetApp();
  1486.   //if (pApp) {
  1487.     int test = 0; /* pApp->GetProfileInt("Language","IntId",0); */
  1488.     LANG_T(path, 0 /*pApp->GetProfileInt("Language","IntId",0)*/ );
  1489.   //}
  1490. }
  1491.  
  1492. int LANG_T(char* path, int l) {
  1493.   if (l>=0) {
  1494.     QLANG_T(l);
  1495.     htslang_load(NULL, path);
  1496.   }
  1497.   return QLANG_T(-1);  // 0=default (english)
  1498. }
  1499.  
  1500. int LANG_SEARCH(char* path, char* iso) {
  1501.   char lang_str[1024];
  1502.   int i = 0;
  1503.   int curr_lng=LANG_T(path, -1);
  1504.   int found = 0;
  1505.   unsigned long int adr = 0;
  1506.   do {
  1507.     QLANG_T(i);
  1508.     strcpybuff(lang_str,"LANGUAGE_ISO");
  1509.     htslang_load(lang_str, path);
  1510.     if (strfield(iso, lang_str)) {
  1511.       found = i;
  1512.     }
  1513.     i++;
  1514.   } while(strlen(lang_str) > 0);
  1515.   QLANG_T(curr_lng);
  1516.   return found;
  1517. }
  1518.  
  1519. int LANG_LIST(char* path, char* buffer) {
  1520.   char lang_str[1024];
  1521.   int i = 0;
  1522.   int curr_lng=LANG_T(path, -1);
  1523.   int found = 0;
  1524.   buffer[0] = '\0';
  1525.   do {
  1526.     QLANG_T(i);
  1527.     strcpybuff(lang_str, "LANGUAGE_NAME");
  1528.     htslang_load(lang_str, path);
  1529.     if (strlen(lang_str) > 0) {
  1530.       if (buffer[0])
  1531.         strcatbuff(buffer, "\n");
  1532.       strcatbuff(buffer, lang_str);
  1533.     }
  1534.     i++;
  1535.   } while(strlen(lang_str) > 0);
  1536.   QLANG_T(curr_lng);
  1537.   return i;
  1538. }
  1539.  
  1540. int QLANG_T(int l) {
  1541.   static int lng=0;
  1542.   if (l>=0) {
  1543.     lng=l;
  1544.   }
  1545.   return lng;  // 0=default (english)
  1546. }
  1547.  
  1548. char* LANGSEL(char* name) {
  1549.   unsigned long int adr = 0;
  1550.   if (NewLangStr)
  1551.   if (!inthash_read(NewLangStr,name,(long int *)&adr))
  1552.     adr=0;
  1553.   if (adr) {
  1554.     return (char*)adr;
  1555.   }
  1556.   return "";
  1557. }
  1558.  
  1559. char* LANGINTKEY(char* name) {
  1560.   unsigned long int adr=0;
  1561.   if (NewLangStrKeys)
  1562.   if (!inthash_read(NewLangStrKeys,name,(long int *)&adr))
  1563.     adr=0;
  1564.   if (adr) {
  1565.     return (char*)adr;
  1566.   }
  1567.   return "";
  1568. }
  1569.  
  1570. char* gethomedir(void) {
  1571.   char* home = getenv( "HOME" );
  1572.   if (home)
  1573.     return home;
  1574.   else
  1575.     return ".";
  1576. }
  1577.  
  1578. int linput_cpp(FILE* fp,char* s,int max) {
  1579.   int rlen=0;
  1580.   s[0]='\0';
  1581.   do {
  1582.     int ret;
  1583.     if (rlen>0)
  1584.     if (s[rlen-1]=='\\')
  1585.       s[--rlen]='\0';      // couper \ final
  1586.     // lire ligne
  1587.     ret=linput_trim(fp,s+rlen,max-rlen);
  1588.     if (ret>0)
  1589.       rlen+=ret;
  1590.   } while((s[max(rlen-1,0)]=='\\') && (rlen<max));
  1591.   return rlen;
  1592. }
  1593.  
  1594. // copy of concat
  1595. typedef struct {
  1596.   char buff[16][HTS_URLMAXSIZE*2*2];
  1597.   int rol;
  1598. } concat_strc;
  1599. char* concat(const char* a,const char* b) {
  1600.   static concat_strc* strc = NULL;
  1601.   if (strc == NULL) {
  1602.     strc = (concat_strc*) calloc(16, sizeof(concat_strc));
  1603.   }
  1604.   strc->rol=((strc->rol+1)%16);    // roving pointer
  1605.   strcpybuff(strc->buff[strc->rol],a);
  1606.   if (b) strcatbuff(strc->buff[strc->rol],b);
  1607.   return strc->buff[strc->rol];
  1608. }
  1609. #ifdef _WIN32
  1610. char* __fconv(char* a) {
  1611.   int i;
  1612.   for(i=0;i<(int) strlen(a);i++)
  1613.     if (a[i]=='/')  // convertir
  1614.       a[i]='\\';
  1615.   return a;
  1616. }
  1617. char* fconcat(char* a,char* b) {
  1618.   return __fconv(concat(a,b));
  1619. }
  1620. char* fconv(char* a) {
  1621.   return __fconv(concat(a,""));
  1622. }
  1623. #endif
  1624.  
  1625. /* *** Various functions *** */
  1626.  
  1627.  
  1628. int fexist(char* s) {
  1629.   struct stat st;
  1630.   memset(&st, 0, sizeof(st));
  1631.   if (stat(s, &st) == 0) {
  1632.     if (S_ISREG(st.st_mode)) {
  1633.       return 1;
  1634.     }
  1635.   }
  1636.   return 0;
  1637.  
  1638. int linput(FILE* fp,char* s,int max) {
  1639.   int c;
  1640.   int j=0;
  1641.   do {
  1642.     c=fgetc(fp);
  1643.     if (c!=EOF) {
  1644.       switch(c) {
  1645.         case 13: break;  // sauter CR
  1646.         case 10: c=-1; break;
  1647.         case 0: case 9: case 12: break;  // sauter ces caractΦres
  1648.         default: s[j++]=(char) c; break;
  1649.       }
  1650.     }
  1651.   }  while((c!=-1) && (c!=EOF) && (j<(max-1)));
  1652.   s[j]='\0';
  1653.   return j;
  1654. }
  1655.  
  1656. int linput_trim(FILE* fp,char* s,int max) {
  1657.   int rlen=0;
  1658.   char* ls=(char*) malloct(max+2);
  1659.   s[0]='\0';
  1660.   if (ls) {
  1661.     char* a;
  1662.     // lire ligne
  1663.     rlen=linput(fp,ls,max);
  1664.     if (rlen) {
  1665.       // sauter espaces et tabs en fin
  1666.       while( (rlen>0) && is_realspace(ls[max(rlen-1,0)]) )
  1667.         ls[--rlen]='\0';
  1668.       // sauter espaces en dΘbut
  1669.       a=ls;
  1670.       while((rlen>0) && ((*a==' ') || (*a=='\t'))) {
  1671.         a++;
  1672.         rlen--;
  1673.       }
  1674.       if (rlen>0) {
  1675.         memcpy(s,a,rlen);      // can copy \0 chars
  1676.         s[rlen]='\0';
  1677.       }
  1678.     }
  1679.     //
  1680.     freet(ls);
  1681.   }
  1682.   return rlen;
  1683. }
  1684.  
  1685. int linputsoc(T_SOC soc, char* s, int max) {
  1686.   int c;
  1687.   int j=0;
  1688.   do {
  1689.     unsigned char ch;
  1690.     if (recv(soc, &ch, 1, 0) == 1) {
  1691.       c = ch;
  1692.     } else {
  1693.       c = EOF;
  1694.     }
  1695.     if (c!=EOF) {
  1696.       switch(c) {
  1697.         case 13: break;  // sauter CR
  1698.         case 10: c=-1; break;
  1699.         case 9: case 12: break;  // sauter ces caractΦres
  1700.         default: s[j++]=(char) c; break;
  1701.       }
  1702.     }
  1703.   }  while((c!=-1) && (c!=EOF) && (j<(max-1)));
  1704.   s[j]='\0';
  1705.   return j;
  1706. }
  1707.  
  1708. int linputsoc_t(T_SOC soc, char* s, int max, int timeout) {
  1709.   if (check_readinput_t(soc, timeout)) {
  1710.     return linputsoc(soc, s, max);
  1711.   }
  1712.   return -1;
  1713. }
  1714.  
  1715. // check if data is available
  1716. int check_readinput(htsblk* r) {
  1717.   if (r->soc != INVALID_SOCKET) {
  1718.     fd_set fds;           // poll structures
  1719.     struct timeval tv;          // structure for select
  1720.     FD_ZERO(&fds);
  1721.     FD_SET(r->soc,&fds);           
  1722.     tv.tv_sec=0;
  1723.     tv.tv_usec=0;
  1724.     select(r->soc + 1,&fds,NULL,NULL,&tv);
  1725.     if (FD_ISSET(r->soc,&fds))
  1726.       return 1;
  1727.     else
  1728.       return 0;
  1729.   } else
  1730.     return 0;
  1731. }
  1732.  
  1733. // check if data is available
  1734. int check_readinput_t(T_SOC soc, int timeout) {
  1735.   if (soc != INVALID_SOCKET) {
  1736.     fd_set fds;           // poll structures
  1737.     struct timeval tv;          // structure for select
  1738.     FD_ZERO(&fds);
  1739.     FD_SET(soc,&fds);           
  1740.     tv.tv_sec=timeout;
  1741.     tv.tv_usec=0;
  1742.     select(soc + 1,&fds,NULL,NULL,&tv);
  1743.     if (FD_ISSET(soc,&fds))
  1744.       return 1;
  1745.     else
  1746.       return 0;
  1747.   } else
  1748.     return 0;
  1749. }
  1750.  
  1751. int strfield(const char* f,const char* s) {
  1752.   int r=0;
  1753.   while (streql(*f,*s) && ((*f)!=0) && ((*s)!=0)) { f++; s++; r++; }
  1754.   if (*s==0)
  1755.     return r;
  1756.   else
  1757.     return 0;
  1758. }
  1759.  
  1760. int ehexh(char c) {
  1761.   if ((c>='0') && (c<='9')) return c-'0';
  1762.   if ((c>='a') && (c<='f')) c-=('a'-'A');
  1763.   if ((c>='A') && (c<='F')) return (c-'A'+10);
  1764.   return 0;
  1765. }
  1766.  
  1767. int ehex(char* s) {
  1768.   return 16*ehexh(*s)+ehexh(*(s+1));
  1769. }
  1770.  
  1771. void unescapehttp(char* s, String* tempo) {
  1772.   int i;
  1773.   for (i=0;i<(int) strlen(s);i++) {
  1774.     if (s[i]=='%' && s[i+1]=='%') {
  1775.       i++;
  1776.       StringAddchar(tempo, '%');
  1777.     } else if (s[i]=='%') {
  1778.       char hc;
  1779.       i++;
  1780.       hc = (char) ehex(s+i);
  1781.       StringAddchar(tempo, (char) hc);
  1782.       i++;    // sauter 2 caractΦres finalement
  1783.     }
  1784.     else if (s[i]=='+') {
  1785.       StringAddchar(tempo, ' ');
  1786.     }
  1787.     else
  1788.       StringAddchar(tempo, s[i]);
  1789.   }
  1790. }
  1791.  
  1792. /* same, except + */
  1793. void unescapeini(char* s, String* tempo) {
  1794.   int i;
  1795.   char lastc=0;
  1796.   for (i=0;i<(int) strlen(s);i++) {
  1797.     if (s[i]=='%' && s[i+1]=='%') {
  1798.       i++;
  1799.       StringAddchar(tempo, lastc = '%');
  1800.     } else if (s[i]=='%') {
  1801.       char hc;
  1802.       i++;
  1803.       hc = (char) ehex(s+i);
  1804.       if (!is_retorsep(hc) || !is_retorsep(lastc)) {
  1805.         StringAddchar(tempo, lastc = (char) hc);
  1806.       }
  1807.       i++;    // sauter 2 caractΦres finalement
  1808.     }
  1809.     else
  1810.       StringAddchar(tempo, lastc = s[i]);
  1811.   }
  1812. }
  1813.  
  1814.